home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-19
/
iritsm3s.zip
/
CAGD_AUX.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-02
|
24KB
|
751 lines
/******************************************************************************
* Cagd_aux.c - auxiliary routine to interface to different free from types. *
*******************************************************************************
* Written by Gershon Elber, July. 90. *
******************************************************************************/
#include "cagd_loc.h"
/******************************************************************************
* Given a crv and parameter value t, evaluate the curve at t. *
******************************************************************************/
CagdRType *CagdCrvEval(CagdCrvStruct *Crv, CagdRType t)
{
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
return BzrCrvEvalAtParam(Crv, t);
case CAGD_CBSPLINE_TYPE:
return BspCrvEvalAtParam(Crv, t);
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
return NULL;
}
}
/******************************************************************************
* Given a srf and parameter values u,v, evaluate the surface at u,v. *
******************************************************************************/
CagdRType *CagdSrfEval(CagdSrfStruct *Srf, CagdRType u, CagdRType v)
{
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
return BzrSrfEvalAtParam(Srf, u, v);
case CAGD_SBSPLINE_TYPE:
return BspSrfEvalAtParam(Srf, u, v);
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
}
/******************************************************************************
* Given a curve - subdivide it into two at the given parametric value. *
* Returns pointer to first curve in a list of two curves (subdivided ones). *
******************************************************************************/
CagdCrvStruct *CagdCrvSubdivAtParam(CagdCrvStruct *Crv, CagdRType t)
{
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
return BzrCrvSubdivAtParam(Crv, t);
case CAGD_CBSPLINE_TYPE:
return BspCrvSubdivAtParam(Crv, t);
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
return NULL;
}
}
/******************************************************************************
* Given a curve - returns a sub region within the specified domain. *
******************************************************************************/
CagdCrvStruct *CagdCrvRegionFromCrv(CagdCrvStruct *Crv, CagdRType t1,
CagdRType t2)
{
CagdRType TMin, TMax;
CagdCrvStruct *Crvs;
CagdBType
NewCrv = FALSE;
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
TMin = 0.0;
TMax = 1.0;
break;
case CAGD_CBSPLINE_TYPE:
BspCrvDomain(Crv, &TMin, &TMax);
break;
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
return NULL;
}
if (t1 > t2) SWAP(CagdRType, t1, t2);
if (!APX_EQ(t1, TMin)) {
Crvs = CagdCrvSubdivAtParam(Crv, t1);
Crv = Crvs -> Pnext;
Crvs -> Pnext = NULL;
CagdCrvFree(Crvs); /* Free the first region. */
NewCrv = TRUE;
}
if (APX_EQ(t2, TMax))
return NewCrv ? Crv : CagdCrvCopy(Crv);
else {
Crvs = CagdCrvSubdivAtParam(Crv, t2);
if (NewCrv) CagdCrvFree(Crv);
CagdCrvFree(Crvs -> Pnext); /* Free the second region. */
Crvs -> Pnext = NULL;
return Crvs; /* Returns the first region. */
}
}
/******************************************************************************
* Given a curve - refine it at the given n knots as defined by vector t. *
* If Replace is TRUE, the values replaces current vector instead. *
* Returns pointer to refined crv (Note Bezier will be converted into spline). *
******************************************************************************/
CagdCrvStruct *CagdCrvRefineAtParams(CagdCrvStruct *Crv, CagdBType Replace,
CagdRType *t, int n)
{
CagdCrvStruct *BspCrv, *TCrv;
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
BspCrv = CnvrtBezier2BsplineCrv(Crv);
TCrv = BspCrvKnotInsertNDiff(BspCrv, Replace, t, n);
CagdCrvFree(BspCrv);
return TCrv;
case CAGD_CBSPLINE_TYPE:
return BspCrvKnotInsertNDiff(Crv, Replace, t, n);
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
return NULL;
}
}
/******************************************************************************
* Return a new curve reversed by reversing the ctl polygon. *
******************************************************************************/
CagdCrvStruct *CagdCrvReverse(CagdCrvStruct *Crv)
{
CagdBType
IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
int i, Len, Col,
Length = Crv -> Length,
MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
CagdCrvStruct
*ReversedCrv = CagdCrvCopy(Crv);
CagdRType *KV,
**Points = ReversedCrv -> Points;
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
case CAGD_CBSPLINE_TYPE:
break;
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
return NULL;
}
/* Reverse the Ctl Polygon: */
Len = Length / 2;
for (Col = 0; Col < Len; Col++)
for (i = IsNotRational; i <= MaxCoord; i++)
SWAP(CagdRType,
Points[i][Col],
Points[i][Length - Col - 1]);
/* Reverse the knot vector if it exists: */
if (Crv -> GType == CAGD_CBSPLINE_TYPE &&
Crv -> KnotVector != NULL) {
KV = BspKnotReverse(Crv -> KnotVector, Crv -> Order + Length);
CagdFree((VoidPtr) ReversedCrv -> KnotVector);
ReversedCrv -> KnotVector = KV;
}
return ReversedCrv;
}
/******************************************************************************
* Return a new curve representing the same curve but with degree raised. *
******************************************************************************/
CagdCrvStruct *CagdCrvDegreeRaise(CagdCrvStruct *Crv)
{
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
return BzrCrvDegreeRaise(Crv);
case CAGD_CBSPLINE_TYPE:
return BspCrvDegreeRaise(Crv);
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
}
/******************************************************************************
* Return a new surface representing the same surface but with degree raised. *
******************************************************************************/
CagdSrfStruct *CagdSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir)
{
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
return BzrSrfDegreeRaise(Srf, Dir);
case CAGD_SBSPLINE_TYPE:
return BspSrfDegreeRaise(Srf, Dir);
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
}
/******************************************************************************
* Extracts an iso curve from the surface as spcified by Dir and t. *
******************************************************************************/
CagdCrvStruct *CagdCrvFromSrf(CagdSrfStruct *Srf, CagdRType t,
CagdSrfDirType Dir)
{
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
return BzrSrfCrvFromSrf(Srf, t, Dir);
case CAGD_SBSPLINE_TYPE:
return BspSrfCrvFromSrf(Srf, t, Dir);
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
}
/******************************************************************************
* Extracts a curve from the surface as spcified by Dir and Index. *
* The curve is constructed as a single ROW/COL of the original surface. *
* Note this curve may be not on the surface! *
******************************************************************************/
CagdCrvStruct *CagdCrvFromMesh(CagdSrfStruct *Srf, int Index,
CagdSrfDirType Dir)
{
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
return BzrSrfCrvFromMesh(Srf, Index, Dir);
case CAGD_SBSPLINE_TYPE:
return BspSrfCrvFromMesh(Srf, Index, Dir);
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
}
/******************************************************************************
* Substitue a row/col from the given curve into the surface as spcified by *
* Dir and Index. Curve must have same PtType/Length and the surface row/col. *
******************************************************************************/
void CagdCrvToMesh(CagdCrvStruct *Crv, int Index,
CagdSrfDirType Dir, CagdSrfStruct *Srf)
{
CagdBType
IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
int i, j,
Length = Crv -> Length,
ULength = Srf -> ULength,
VLength = Srf -> VLength,
MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
CagdRType *CrvP, *SrfP;
if (Crv -> PType != Srf -> PType ||
Length != (Dir == CAGD_CONST_U_DIR ? VLength : ULength))
FATAL_ERROR(CAGD_ERR_PT_OR_LEN_MISMATCH);
switch (Dir) {
case CAGD_CONST_U_DIR:
if (Index + 1 > ULength)
FATAL_ERROR(CAGD_ERR_INDEX_NOT_IN_MESH);
for (i = IsNotRational; i <= MaxCoord; i++) {
CrvP = Crv -> Points[i];
SrfP = Srf -> Points[i] + Index * CAGD_NEXT_U(Srf);
for (j = 0; j < Length; j++) {
*SrfP = *CrvP++;
SrfP += CAGD_NEXT_V(Srf);
}
}
break;
case CAGD_CONST_V_DIR:
if (Index + 1 > VLength)
FATAL_ERROR(CAGD_ERR_INDEX_NOT_IN_MESH);
for (i = IsNotRational; i <= MaxCoord; i++) {
CrvP = Crv -> Points[i];
SrfP = Srf -> Points[i] + Index * CAGD_NEXT_V(Srf);;
for (j = 0; j < Length; j++) {
*SrfP = *CrvP++;
SrfP += CAGD_NEXT_U(Srf);
}
}
break;
default:
FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
break;
}
}
/******************************************************************************
* Given a srf - subdivide it into two at given parametric value in given dir. *
* Returns pointer to first srf in a list of two srfs (subdivided ones). *
******************************************************************************/
CagdSrfStruct *CagdSrfSubdivAtParam(CagdSrfStruct *Srf, CagdRType t,
CagdSrfDirType Dir)
{
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
return BzrSrfSubdivAtParam(Srf, t, Dir);
case CAGD_SBSPLINE_TYPE:
return BspSrfSubdivAtParam(Srf, t, Dir);
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
}
/******************************************************************************
* Given a surface - returns a sub region within the specified domain, dir. *
******************************************************************************/
CagdSrfStruct *CagdSrfRegionFromSrf(CagdSrfStruct *Srf, CagdRType t1,
CagdRType t2, CagdSrfDirType Dir)
{
CagdRType TMin, TMax, R1, R2;
CagdSrfStruct *Srfs;
CagdBType
NewSrf = FALSE;
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
TMin = 0.0;
TMax = 1.0;
break;
case CAGD_SBSPLINE_TYPE:
if (Dir == CAGD_CONST_U_DIR)
BspSrfDomain(Srf, &TMin, &TMax, &R1, &R2);
else
BspSrfDomain(Srf, &R1, &R2, &TMin, &TMax);
break;
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
if (t1 > t2) SWAP(CagdRType, t1, t2);
if (!APX_EQ(t1, TMin)) {
Srfs = CagdSrfSubdivAtParam(Srf, t1, Dir);
Srf = Srfs -> Pnext;
Srfs -> Pnext = NULL;
CagdSrfFree(Srfs); /* Free the first region. */
NewSrf = TRUE;
}
if (APX_EQ(t2, TMax))
return NewSrf ? Srf : CagdSrfCopy(Srf);
else {
Srfs = CagdSrfSubdivAtParam(Srf, t2, Dir);
if (NewSrf) CagdSrfFree(Srf);
CagdSrfFree(Srfs -> Pnext); /* Free the second region. */
Srfs -> Pnext = NULL;
return Srfs; /* Returns the first region. */
}
}
/******************************************************************************
* Given a surface - refine it at the given n knots as defined by vector t. *
* If Replace is TRUE, the values replaces current vector instead. *
* Returns pointer to refined srf (Note Bezier will be converted into spline). *
******************************************************************************/
CagdSrfStruct *CagdSrfRefineAtParams(CagdSrfStruct *Srf, CagdSrfDirType Dir,
CagdBType Replace, CagdRType *t, int n)
{
CagdSrfStruct *BspSrf, *TSrf;
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
BspSrf = CnvrtBezier2BsplineSrf(Srf);
TSrf = BspSrfKnotInsertNDiff(BspSrf, Dir, Replace, t, n);
CagdSrfFree(BspSrf);
return TSrf;
case CAGD_SBSPLINE_TYPE:
return BspSrfKnotInsertNDiff(Srf, Dir, Replace, t, n);
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
}
/******************************************************************************
* Given a curve and a parameter value t, returns the tangent direction at t. *
******************************************************************************/
CagdVecStruct *CagdCrvTangent(CagdCrvStruct *Crv, CagdRType t)
{
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
return BzrCrvTangent(Crv, t);
case CAGD_CBSPLINE_TYPE:
return BspCrvTangent(Crv, t);
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
return NULL;
}
}
/******************************************************************************
* Given a curve and a parameter value t, returns the binormal direction at t. *
******************************************************************************/
CagdVecStruct *CagdCrvBiNormal(CagdCrvStruct *Crv, CagdRType t)
{
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
return BzrCrvBiNormal(Crv, t);
case CAGD_CBSPLINE_TYPE:
return BspCrvBiNormal(Crv, t);
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
return NULL;
}
}
/******************************************************************************
* Given a curve and a parameter value t, returns the normal direction at t. *
******************************************************************************/
CagdVecStruct *CagdCrvNormal(CagdCrvStruct *Crv, CagdRType t)
{
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
return BzrCrvNormal(Crv, t);
case CAGD_CBSPLINE_TYPE:
return BspCrvNormal(Crv, t);
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
return NULL;
}
}
/******************************************************************************
* Given a curve and an offset amount Offset, returns an approximation to the *
* offset curve by offseting the control polygon in the normal direction. *
******************************************************************************/
CagdCrvStruct *CagdCrvOffset(CagdCrvStruct *Crv, CagdRType OffsetDist)
{
CagdBType
IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
int i, j,
MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType),
Order = Crv -> Order,
Length = Crv -> Length;
CagdBType
HasNewKV = FALSE;
CagdVecStruct *N;
CagdCrvStruct
*OffsetCrv = CagdCrvCopy(Crv);
CagdRType *Nodes, *NodePtr,
**Points = OffsetCrv -> Points,
*KV = NULL;
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
HasNewKV = TRUE;
KV = BspKnotUniformOpen(Length, Order, NULL);
break;
case CAGD_CBSPLINE_TYPE:
KV = Crv -> KnotVector;
break;
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
return NULL;
}
Nodes = BspKnotNodes(KV, Length + Order, Order);
NodePtr = Nodes;
if (IsNotRational)
for (j = 0; j < Length; j++) {
N = CagdCrvNormal(Crv, *NodePtr++);
for (i = 1; i <= MaxCoord; i++)
Points[i][j] += N -> Vec[i - 1] * OffsetDist;
}
else
for (j = 0; j < Length; j++) {
N = CagdCrvNormal(Crv, *NodePtr++);
for (i = 1; i <= MaxCoord; i++)
Points[i][j] = Points[i][j] +
N -> Vec[i - 1] * OffsetDist * Points[W][j];
}
if (HasNewKV)
CagdFree((VoidPtr) KV);
CagdFree((VoidPtr) Nodes);
return OffsetCrv;
}
/******************************************************************************
* Given a srf and parameter value u,v, returns the tangent direction in Dir. *
******************************************************************************/
CagdVecStruct *CagdSrfTangent(CagdSrfStruct *Srf, CagdRType u, CagdRType v,
CagdSrfDirType Dir)
{
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
return BzrSrfTangent(Srf, u, v, Dir);
case CAGD_SBSPLINE_TYPE:
return BspSrfTangent(Srf, u, v, Dir);
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
}
/******************************************************************************
* Given a srf and parameter values u,v, returns the surface normal at u,v. *
******************************************************************************/
CagdVecStruct *CagdSrfNormal(CagdSrfStruct *Srf, CagdRType u, CagdRType v)
{
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
return BzrSrfNormal(Srf, u, v);
case CAGD_SBSPLINE_TYPE:
return BspSrfNormal(Srf, u, v);
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
}
/******************************************************************************
* Given a surface and an offset amount Offset, returns an approximation to *
* the offset surface by offseting the control mesh in the normal direction. *
******************************************************************************/
CagdSrfStruct *CagdSrfOffset(CagdSrfStruct *Srf, CagdRType OffsetDist)
{
CagdBType
IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
int i, Row, Col,
MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType),
UOrder = Srf -> UOrder,
VOrder = Srf -> VOrder,
ULength = Srf -> ULength,
VLength = Srf -> VLength;
CagdBType
HasNewKV = FALSE;
CagdVecStruct *N;
CagdSrfStruct
*OffsetSrf = CagdSrfCopy(Srf);
CagdRType *UNodes, *VNodes, *UNodePtr, *VNodePtr,
**Points = OffsetSrf -> Points,
*UKV = NULL,
*VKV = NULL;
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
HasNewKV = TRUE;
UKV = BspKnotUniformOpen(ULength, UOrder, NULL);
VKV = BspKnotUniformOpen(VLength, VOrder, NULL);
break;
case CAGD_SBSPLINE_TYPE:
UKV = Srf -> UKnotVector;
VKV = Srf -> VKnotVector;
break;
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
return NULL;
}
UNodes = BspKnotNodes(UKV, ULength + UOrder, UOrder);
VNodes = BspKnotNodes(VKV, VLength + VOrder, VOrder);
if (IsNotRational)
for (Row = 0, VNodePtr = VNodes; Row < VLength; Row++, VNodePtr++)
for (Col = 0, UNodePtr = UNodes; Col < ULength; Col++, UNodePtr++) {
N = CagdSrfNormal(Srf, *UNodePtr, *VNodePtr);
for (i = 1; i <= MaxCoord; i++)
Points[i][CAGD_MESH_UV(OffsetSrf, Col, Row)] +=
N -> Vec[i - 1] * OffsetDist;
}
else
for (Row = 0, VNodePtr = VNodes; Row < VLength; Row++, VNodePtr++)
for (Col = 0, UNodePtr = UNodes; Col < ULength; Col++, UNodePtr++) {
N = CagdSrfNormal(Srf, *UNodePtr, *VNodePtr);
for (i = 1; i <= MaxCoord; i++)
Points[i][CAGD_MESH_UV(OffsetSrf, Col, Row)] +=
N -> Vec[i - 1] * OffsetDist *
Points[W][CAGD_MESH_UV(OffsetSrf, Col, Row)];
}
if (HasNewKV) {
CagdFree((VoidPtr) UKV);
CagdFree((VoidPtr) VKV);
}
CagdFree((VoidPtr) UNodes);
CagdFree((VoidPtr) VNodes);
return OffsetSrf;
}
/******************************************************************************
* Return a new reversed surface by reversing in U direction the control mesh. *
******************************************************************************/
CagdSrfStruct *CagdSrfReverse(CagdSrfStruct *Srf)
{
CagdBType
IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
int i, Len, Row, Col,
ULength = Srf -> ULength,
VLength = Srf -> VLength,
MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
CagdSrfStruct
*ReversedSrf = CagdSrfCopy(Srf);
CagdRType *KV,
**Points = ReversedSrf -> Points;
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
case CAGD_SBSPLINE_TYPE:
break;
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
/* Reverse the Mesh: */
Len = ULength / 2;
for (Row = 0; Row < VLength; Row++)
for (Col = 0; Col < Len; Col++)
for (i = IsNotRational; i <= MaxCoord; i++)
SWAP(CagdRType,
Points[i][Row * ULength + Col],
Points[i][Row * ULength + ULength - Col - 1]);
/* Reverse the U knot vector if it exists: */
if (Srf -> GType == CAGD_SBSPLINE_TYPE &&
Srf -> UKnotVector != NULL) {
KV = BspKnotReverse(Srf -> UKnotVector, Srf -> UOrder + ULength);
CagdFree((VoidPtr) ReversedSrf -> UKnotVector);
ReversedSrf -> UKnotVector = KV;
}
return ReversedSrf;
}
/******************************************************************************
* Return a new reversed surface by flipping the U and V directions. *
******************************************************************************/
CagdSrfStruct *CagdSrfReverse2(CagdSrfStruct *Srf)
{
CagdBType
IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
int i, Row, Col,
ULength = Srf -> ULength,
VLength = Srf -> VLength,
MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
CagdSrfStruct
*ReversedSrf = CagdSrfCopy(Srf);
CagdRType
**Points = Srf -> Points,
**RevPoints = ReversedSrf -> Points;
switch (Srf -> GType) {
case CAGD_SBEZIER_TYPE:
case CAGD_SBSPLINE_TYPE:
break;
case CAGD_SPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
return NULL;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
return NULL;
}
/* Reverse the Mesh: */
for (Row = 0; Row < VLength; Row++)
for (Col = 0; Col < ULength; Col++)
for (i = IsNotRational; i <= MaxCoord; i++)
RevPoints[i][Col * VLength + Row] =
Points[i][Row * ULength + Col];
/* Swap the U and the V knot vectors if the exists: */
if (Srf -> GType == CAGD_SBSPLINE_TYPE) {
SWAP(CagdRType *,
ReversedSrf -> UKnotVector, ReversedSrf -> VKnotVector);
}
/* And swap the orders and lengths. */
SWAP(int, ReversedSrf -> UOrder, ReversedSrf -> VOrder);
SWAP(int, ReversedSrf -> ULength, ReversedSrf -> VLength);
return ReversedSrf;
}